Closed
Description
I'm looking for a page navigation lock feature or alternative like phantomjs has http://phantomjs.org/api/webpage/property/navigation-locked.html
Metadata
Assignees
Type
Projects
Milestone
Relationships
Development
No branches or pull requests
Activity
aslushnikov commentedon Sep 25, 2017
@davedmarketing no, there's no navigation lock for now. Could you please share your usage scenarios - why would you need one?
caddave commentedon Sep 25, 2017
@aslushnikov For me I was looking into it for a site that had unpredictable behavior and was getting redirected randomly or elements with links popping up randomly and my script was clicking on them accidentally.
GuilloOme commentedon Oct 23, 2017
here is my use case (close to @davedmarketing one):
Context: Using puppeteer to inject a probe in a page and retrieving urls related to the given page.
Requirements: Staying on a the page as long as we do not have all the urls.
Behavior: The probe "click/hover/keystroke" every part of the page and it's commun to hit a "navigation away" action (through a
window.location='url'orwindow.location.href='url'call)GuilloOme commentedon Nov 10, 2017
I finally found a workaround to this (ie. blocking navigation while retrieving the destination url)… with a custom chrome extension.
But, because of #659, it CAN'T be used with
headless: false. Hopefully, this should be resolved with #872 .Why a chrome extension?
Short version: because of DOM insolation
Long version:
At the page level, we can block navigation away by hijacking the
window.onbeforeunloadevent but we will not be able to know what is the destination.The only way (I found) to prevent navigation is to use the
chrome.webRequest.onBeforeRequestevent available at extension level because it provide a way to manipulate the request before it is issue to the network level (so before the navigation start).How it works?
We need here a content-script to pass message between the extension and puppeteer (through the page)
here the snippet of the blocking logic in the extension:
Full code available: https://gist.github.com/GuilloOme/2bd651e5154407d2d2165278d5cd7cdb
aslushnikov commentedon Nov 15, 2017
@GuilloOme interesting approach! You can also implement this idea using request interception. This way you won't need to run extension.
GuilloOme commentedon Nov 15, 2017
@aslushnikov, correct me if I'm mistaken:
I did check it but I couldn't find a way to differentiate a "navigation" request type from a "document" request type. The chrome API give me
main_frameandsub_frameas a request type which is more precise thandocumentprovided by the DevTools Protocol. As I found out, the DevTools protocol identify the resource typedocumentonly based on themimeType(see my answer on stackoverflow)page.setRequestInterception(true)with an extension usingwebRequestBlockingpermission #1397sukhjitsingh-impactradius commentedon Nov 21, 2017
@aslushnikov rather than a navigation lock I wanted to click and open a new tab for each element on the page and setrequestinterception for each new page, but the request interception is not added in time to catch the initial redirect. I've attemped @GuilloOme's solution like above using chrome.webRequest but like he says above it lacks a way to connect the extension to the puppeteer code (or I'm not using it correctly). I've scoured the issues and stackoverflow, is there a way to set requestinterception at the browser level? If not, do you have any suggestions?
^This is where I'm at right now, but again, hitting that newPage.on() too late.
GuilloOme commentedon Nov 21, 2017
@sukhjitsingh-impactradius, communication between the extension and the node process is not straightforward but possible, I did that here.
To achieve that, you have to use messaging between the extension and the page (through the
content.js, see: l.22 of my gist). Then, you have to inject some code in the page DOM to handle the message in the page usingpage.evaluate()and usepage.exposeFunction()to return the result to puppeteer.As I said, not straightforward but possible 😉
aslushnikov commentedon Nov 21, 2017
@GuilloOme ah indeed, you're right. My suggestion wouldn't work for you then.
@sukhjitsingh-impactradius that's a good usecase, thank you. @caseq: this might be another point towards browser-wide request interception
sukhjitsingh-impactradius commentedon Jan 15, 2018
@aslushnikov is there work being done for this request or is there possibly somewhere you think upstream where I can log a ticket for this, if it hasn't already?
aslushnikov commentedon Jan 16, 2018
@sukhjitsingh-impactradius not yet.
You can file a ticket on
crbug.comagainst devtools protocol, it will help us with bookkeeping.10 remaining items
Wildhoney commentedon Feb 8, 2019
@Qianlitp good thinking! Something like the following seems to work just fine:
@dave-dm although a good answer too, you can't prevent page navigation from
onClickevents, etc...jiangfengming commentedon Feb 26, 2019
req.respond({ status: 204 })can prevent the navigation by js.panthony commentedon Mar 13, 2019
The solution suggested by by @jiangfengming was working well until the new
1.13.0release wherepage.gotohangs until it timeout, unfortunately.aslushnikov commentedon Mar 15, 2019
@panthony works just fine for me with 1.13.0. One correction however is to use
request.abortinstead ofrequest.respond- this way we can properly abort navigation.Try running the following script and than manually navigating from "example.com" to any other website:
This is the recommended way to implement navigation locks.
panthony commentedon Mar 15, 2019
@aslushnikov Ok, I started to return 204 when aborting the navigation request made goto failed:
#3421 (comment)
Guess I'll give abort a try again :)
aslushnikov commentedon Mar 15, 2019
@panthony let me know how it goes!
rymdhund commentedon Apr 5, 2019
@aslushnikov The code you linked timeouts for me every time when I change example.com to a page that does
window.location = 'http://google.com'. Both on 1.13.0 and 1.14.0. Maybe it's the interception that is causing trouble again?aslushnikov commentedon Apr 5, 2019
@rymdhund not sure, the following works just fine for me.
Note: the
page.gotowill throw theERR:ABORTEDsince you abort the navigation, so you should handle the exception.panthony commentedon May 14, 2019
@aslushnikov Aborting the navigation request like suggested above will make the
gotohang if you happen to usewaitUntil: [ 'networkidle2' ].DCtheTall commentedon Mar 25, 2020
Hey all, now that Chrome is planning on deprecating the Network.* Devtools Protocol API, has anyone found a way to do this using the new Fetch Devtools API?